package be.castanea.client;

import be.castanea.client.controller.FrontController;
import be.castanea.client.delegate.ServerDelegate;
import be.castanea.client.view.account.AccountState;
import be.castanea.client.view.login.LoginState;
import be.castanea.client.view.ingame.IngameState;
import be.castanea.common.util.GenericEvent;
import be.castanea.common.util.MessageUtil;
import com.jmex.game.StandardGame;
import com.jmex.game.state.GameStateManager;
import com.sun.sgs.client.ClientChannel;
import com.sun.sgs.client.ClientChannelListener;
import com.sun.sgs.client.simple.SimpleClient;
import com.sun.sgs.client.simple.SimpleClientListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.PasswordAuthentication;
import java.nio.ByteBuffer;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Castanea
 * 2009
 * @author Geert van Leemputten, Steven Rymenans, Bart Van Hooydonck
 */
public class CastaneaClient implements SimpleClientListener {

    private static StandardGame game;
    private static SimpleClient simpleClient;

    public CastaneaClient(StandardGame game) {
        CastaneaClient.game = game;
        CastaneaClient.simpleClient = new SimpleClient(this);
        GameStateManager.getInstance().attachChild(new LoginState());
    }

    public static void login() throws IOException {
        Properties hostProps = new Properties();
        try {
            hostProps.load(new FileInputStream("host.properties"));
        } catch (FileNotFoundException ex) {
            hostProps.put("host", "127.0.0.1");
            hostProps.put("port", "1139");
            hostProps.store(new FileOutputStream("host.properties"), "Host information");
        }
        simpleClient.login(hostProps);
    }

    public static void send(GenericEvent event) {
        try {
            simpleClient.send(MessageUtil.encode(event));
        } catch (IOException ex) {
            Logger.getLogger(CastaneaClient.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void disconnect() {
        simpleClient.logout(true);
    }

    public static StandardGame getGame() {
        return game;
    }

    public static LoginState getLoginState() {
        return (LoginState) GameStateManager.getInstance().getChild("LOGIN");
    }

    public static AccountState getAccountState() {
        return (AccountState) GameStateManager.getInstance().getChild("ACCOUNT");
    }

    public static IngameState getIngameState() {
        return (IngameState) GameStateManager.getInstance().getChild("INGAME");
    }

    public PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(getLoginState().getUsername(), getLoginState().getPassword().toCharArray());
    }

    public void loggedIn() {
        getLoginState().setActive(false);
        GameStateManager.getInstance().attachChild(new IngameState());
        ServerDelegate.dispatchJoin();
    }

    public void loginFailed(String reason) {
        Logger.getLogger(CastaneaClient.class.getName()).log(Level.SEVERE, "LOGIN FAILED: " + reason);
        System.exit(0);
    }

    public ClientChannelListener joinedChannel(ClientChannel channel) {
        return new ClientChannelListener() {

            public void receivedMessage(ClientChannel channel, ByteBuffer message) {
                FrontController.getInstance().dispatchEvent(MessageUtil.decode(message));
            }

            public void leftChannel(ClientChannel channel) {
            }
        };
    }

    public void receivedMessage(ByteBuffer message) {
        FrontController.getInstance().dispatchEvent(MessageUtil.decode(message));
    }

    public void reconnecting() {
        Logger.getLogger(CastaneaClient.class.getName()).log(Level.SEVERE, "RECONNECTING");
    }

    public void reconnected() {
        Logger.getLogger(CastaneaClient.class.getName()).log(Level.SEVERE, "RECONNECTED");
    }

    public void disconnected(boolean graceful, String reason) {
        GameStateManager.getInstance().detachAllChildren();
        GameStateManager.getInstance().attachChild(new LoginState());
    }
}
